﻿#region Copyright
//       Copyright (c) 2009 - Antoine Jaussoin - http://www.jaussoin.com/blog/
// 
//        This program is free software: you can redistribute it and/or modify
//        it under the terms of the GNU General Public License as published by
//        the Free Software Foundation, either version 3 of the License, or
//        (at your option) any later version.
// 
//        This program is distributed in the hope that it will be useful,
//        but WITHOUT ANY WARRANTY; without even the implied warranty of
//        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//        GNU General Public License for more details.
// 
//        You should have received a copy of the GNU General Public License
//        along with this program.  If not, see <http://www.gnu.org/licenses/>.
#endregion
using System;
using FT.Architecture.Utils.ExtensionMethods;
using FT.Architecture.Utils.Serialisation;

namespace FT.Architecture.Entities
{
    /// <summary>
    /// Class that will help to parse things into and back from a string
    /// </summary>
    public class IdParser
    {
        /// <summary>
        /// Get a string representation of the ID given in parameter
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="id"></param>
        /// <returns></returns>
        public static string ToString<T>(T id)
        {
            return ToString((object)id);
        }

        /// <summary>
        /// Get a string representation of the ID given in parameter
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public static string ToString(object id)
        {
            Type type = id.GetType();

            if (id is IIdParsable)
            {
                var parsableId = (IIdParsable) id;
                return parsableId.ToIdString();
            }

            if (type.Is<long>() ||
                type.Is<decimal>() ||
                type.Is<int>() ||
                type.Is<double>() ||
                type.Is<string>() //||
                )
            {
                return id.ToString();
            }

            if (type.Is<DateTime>())
            {
                return ((DateTime) id).Ticks.ToString();
            }

            return Serialiser.Serialise(id);
        }

        /// <summary>
        /// Parse a string and returns an ID from it
        /// </summary>
        /// <param name="idType"></param>
        /// <param name="id"></param>
        /// <returns></returns>
        public static object FromString(Type idType, string id)
        {
            if (idType.Is<long>())
                return long.Parse(id);

            if (idType.Is<decimal>())
                return decimal.Parse(id);

            if (idType.Is<int>())
                return int.Parse(id);

            if (idType.Is<double>())
                return double.Parse(id);

            if (idType.Is<DateTime>())
                return new DateTime(long.Parse(id));

            if (idType.Is<string>())
                return id;

            return Serialiser.Deserialise(id);
        }

        /// <summary>
        /// Get a string representation of the ID given in parameter
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="id"></param>
        /// <returns></returns>
        public static T FromString<T>(string id)
        {
            Type type = typeof(T);

            return (T) FromString(type, id);
        }
    }

    /// <summary>
    /// This interface need to be implemented on a composite ID
    /// </summary>
    public interface IIdParsable
    {
        /// <summary>
        /// Serialise the content of the ID into a string
        /// </summary>
        /// <returns></returns>
        string ToIdString();

        /// <summary>
        /// Deserialise the content of the ID from a string
        /// </summary>
        /// <param name="serialisedId"></param>
        void FromIdString(string serialisedId);
    }
}
